# -*- coding: iso-8859-15 -*- 
# mrtn@mrtn.dyn.ee

import win32con, win32gui, win32ui
import array, struct
from threading import Thread

SKYPECONTROLAPI_ATTACH_SUCCESS = 0 
SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION = 1
SKYPECONTROLAPI_ATTACH_REFUSED = 2
SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE = 3
SKYPECONTROLAPI_ATTACH_API_AVAILABLE = 0x8001

COPYDATA_STRUCT = "IIP"

class SkypeApiConnection:

	def __init__ (self):
		self.SkypeControlApiAttach_MsgID = win32gui.RegisterWindowMessage('SkypeControlAPIAttach')
		self.SkypeControlApiDiscover_MsgID = win32gui.RegisterWindowMessage('SkypeControlAPIDiscover')

		self.SkypeAPIWindowHandle = 0
		self.WindowHandle = 0

		self.message_map = {
		    win32con.WM_COPYDATA: self.OnCopyData,
		    win32con.WM_DESTROY: self.OnDestroy,
		    self.SkypeControlApiAttach_MsgID: self.MessageHandler,
		}

		self.InitWindow()

		print "\nSkype API testexample. [#quit, #close, #exit, #connect, #disconnect]\n"

		self.Connect()
	
	def InitWindow (self):
		wc = win32gui.WNDCLASS()
		wc.lpszClassName = 'Skype_api_client'
		wc.lpfnWndProc = self.message_map
		self.hinst = wc.hInstance = win32gui.GetModuleHandle(None)
		self.cAtom = win32gui.RegisterClass(wc)
		self.WindowHandle = win32gui.CreateWindowEx(
			win32con.WS_EX_APPWINDOW|win32con.WS_EX_WINDOWEDGE,
			self.cAtom,
			'Skype_api_client',
			win32con.WS_BORDER|win32con.WS_SYSMENU|win32con.WS_MINIMIZEBOX,
			win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 
			128, 128, 
			0, 0, self.hinst, None)

	def Connect (self):
		if self.SkypeAPIWindowHandle > 0:
			print 'Already connected ! Use #disconnect'
			return

		# broadcast
		print '!!! Broadcasting APIdiscover ' 
		res = win32gui.SendMessage( win32con.HWND_BROADCAST, self.SkypeControlApiDiscover_MsgID, self.WindowHandle, 0)
		if res != 1:
			print '!!! Answer %s' % rep
			self.Disconnect()

	def Disconnect (self):
		self.SkypeAPIWindowHandle = 0
		print '!!! Disconnected '

	def OnCopyData (self, hwnd, msg, wparam, lparam):
		
		size = struct.calcsize(COPYDATA_STRUCT)
		s = win32ui.GetBytes(lparam, size)
		dwData, cbData, lpData = struct.unpack(COPYDATA_STRUCT, s)
		message = win32ui.GetBytes(lpData, cbData)
		
		print '<< ' + message

		return 1
		
	def OnDestroy(self, hwnd, msg, wparam, lparam):     
		win32gui.DestroyWindow(self.WindowHandle)
		try:
			win32gui.UnregisterClass(self.cAtom, self.hinst)
		except: 
			pass
		win32gui.PostQuitMessage(0)

	def MessageHandler (self, hwnd, msg, wparam, lparam):

		if lparam == SKYPECONTROLAPI_ATTACH_SUCCESS :
			self.SkypeAPIWindowHandle = wparam
			print '!!! Connected; to terminate issue #disconnect'
			print 'Sending test ping!'
			self.SendMessage('PING')
		
		elif lparam == SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION :
			print '!!! Pending authorization'

		elif lparam == SKYPECONTROLAPI_ATTACH_REFUSED :
			print '!!! Connection refused'

		elif lparam == SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE :
			print '!!! Skype API not available'

		elif lparam == SKYPECONTROLAPI_ATTACH_API_AVAILABLE :
			print '!!! Try connect now (API available); issue #connect'
	
	def SendMessage (self, message):
		if self.SkypeAPIWindowHandle == 0 :
			print 'Not connected ! Use #connect'
			return

		message = message + '\00'
		
		print '>> ' + message

		# pack message; copydatastruct
		char_buffer = array.array('c', message )
		char_buffer_address, char_buffer_size = char_buffer.buffer_info()
		cds = array.array('c', struct.pack(COPYDATA_STRUCT, 0, char_buffer_size, char_buffer_address ))
		copydata = cds.buffer_info()[0]

		response = win32gui.SendMessage(self.SkypeAPIWindowHandle, win32con.WM_COPYDATA, self.WindowHandle, copydata)
		if response != 1:
			self.Disconnect()

def mainloop ():
	global ApiConnection
	while True:
		line = raw_input()
		line = line.strip()
		
		if line in ['#quit','#exit','#close']:
			break
		elif line == '#connect':
			ApiConnection.Connect()

		elif line == '#disconnect':
			ApiConnection.Disconnect()

		elif len(line) > 0:
			ApiConnection.SendMessage(line)

	#sendmessage self
	win32gui.SendMessage(ApiConnection.WindowHandle, win32con.WM_DESTROY,0,0)
	return 0

if __name__ == '__main__':
	ApiConnection= SkypeApiConnection()
	loop = Thread(target = mainloop)
	loop.start()
	win32gui.PumpMessages() 